package com.sgtech.java.aop.aspect;

import com.sgtech.java.aop.annotation.OperLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @Description: 切面处理
 * @Author laoxu
 * @Date 2021-10-19 14:45
 **/
@Slf4j
@Aspect
@Component
public class OperLogAspect {
    /**
     * 操作日志切入点
     */
    @Pointcut("@annotation(com.sgtech.java.aop.annotation.OperLog)")
    public void operLogPoinCut() {
    }

    @Before("operLogPoinCut()") //在切入点的方法run之前要干的
    public void logBeforeController(JoinPoint joinPoint) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();

        log.info("################请求路径 : " + request.getRequestURL().toString());
        log.info("################请求方式 : " + request.getMethod());
        log.info("################客户端IP : " + request.getRemoteAddr());
        log.info("################方法参数: " + Arrays.toString(joinPoint.getArgs()));

        //下面这个getSignature().getDeclaringTypeName()是获取包+类名的   然后后面的joinPoint.getSignature.getName()获取了方法名
        log.info("################执行方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        //logger.info("################TARGET: " + joinPoint.getTarget());//返回的是需要加强的目标类的对象
        //logger.info("################THIS: " + joinPoint.getThis());//返回的是经过加强后的代理类的对象

    }

    @Around("operLogPoinCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取操作
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        // 获取切入点所在的方法
        Method callMethod = signature.getMethod();
        OperLog opLog = callMethod.getAnnotation(OperLog.class);

        if(opLog != null){
            log.info("请求的系统操作：{}-{}-{}",opLog.operModule(),opLog.operType(),opLog.operDesc());
        }

        Object proceed = pjp.proceed(); //执行目标方法
        return proceed; //返回目标方法执行结果
    }

}
